import routerLink from "./components/routerLink";
import routerView from "./components/routerView.js";
import { createMatch } from "./createMatch";
import { HashHistory } from "./history/hash";
import { HtmlHistory } from "./history/html5";


export let Vue;
export default class VueRouter {
    constructor(options = {}) {
        //   vue-router 核心 1 match核心  [{},{}]  => {'/':{组件相关信息}，'/about':{}}
        ({ match: this.match, addRoutes: this.addRoutes } = createMatch(options.routes || []))
        this.beforeHooks = []
        //浏览器路由管理
        options.mode = options.mode || 'hash'
        switch (options.mode) {
            case 'hash':
                this.history = new HashHistory(this)
                break;
            case 'history':
                this.history = new HtmlHistory(this)
                break;

            default:
                break;
        }
    }
    push(locations) {
        // this.history.transitionTo(locations)
        this.history.push(locations)
    }
    init(app) {//根据路由找到组件
        //获取当前的路由
        const history = this.history
        history.listen((route) => {
            app._route = route
        })
        //jupm to  (nowpath,function)
        const setUpHashLister = () => {
            history.setUpLister()//监听路由跳转
        }
        history.transitionTo(
            history.getCurrentLocation(),
            setUpHashLister
        )
    }
    beforeEach(fn) {
        this.beforeHooks.push(fn)
    }
}

VueRouter.install = (_Vue) => {
    Vue = _Vue;
    //全局组件的挂载
    Vue.component('router-link', routerLink)
    Vue.component('router-view', routerView)
    //每个组件添加router的实列
    Vue.mixin({
        beforeCreate() {
            if (this.$options.router) {
                //将实列放到根上 
                this._router = this.$options.router
                this._routerRoot = this //将父亲的实列暴露出去
                this._router.init(this)
                Vue.util.defineReactive(this, '_route', this._router.history.current)
            } else {
                this._routerRoot = this.$parent && this.$parent._routerRoot
            }
        },
    })

    //代理 this.$route 属性  this.$router 方法
    Object.defineProperty(Vue.prototype, "$router", {
        get() {
            return this._routerRoot._router
        }
    })
    Object.defineProperty(Vue.prototype, "$route", {
        get() {
            return this._routerRoot._route
        }
    })
};
